package com.fm.base.struct;

import java.util.Iterator;

public class DoubleLinkedList<V> {
	private DoubleLinkedNode<V> head;
	private DoubleLinkedNode<V> tail;
	private int size = 0;

	public int size() {
		return size;
	}

	public void add(V value) {
		if (tail == null) {
			head = tail = new DoubleLinkedNode<>(value, null, null);
		} else {
			DoubleLinkedNode<V> temp = new DoubleLinkedNode<>(value, tail, null);
			tail.setNext(temp);
			tail = temp;
		}
		size++;
	}

	public DoubleLinkedNode<V> getHead() {
		return head;
	}

	public DoubleLinkedNode<V> getTail() {
		return tail;
	}

	public void remove(DoubleLinkedNode<V> node) {
		DoubleLinkedNode<V> prev = node.getPrev();
		DoubleLinkedNode<V> next = node.getNext();
		if (prev == null) {
			if (next == null) {
				head = tail = null;
			} else {
				next.setPrev(null);
				head = next;
			}
		} else {
			if (next == null) {
				prev.setNext(null);
				tail = prev;
			} else {
				prev.setNext(node.getNext());
				next.setPrev(node.getPrev());
			}
		}
		size--;
	}

	public void tail(DoubleLinkedNode<V> node) {
		node.setNext(null);
		tail = node;
	}

	public void clear() {
		head = tail = null;
		size = 0;
	}

	public Iterator<V> iterator() {
		return new Iterator<V>() {
			DoubleLinkedNode<V> pre;
			DoubleLinkedNode<V> cur = head;

			@Override
			public boolean hasNext() {
				return cur != null;
			}

			@Override
			public V next() {
				try {
					return cur.getValue();
				} finally {
					pre = cur;
					cur = cur.getNext();
				}
			}

			@Override
			public void remove() {
				DoubleLinkedList.this.remove(pre);
			}
		};
	}
}
